using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using DslCrossModelFramework.ModelTraversal;
using Microsoft.VisualStudio.Modeling;

namespace DslCrossModelFramework.ModelRelationship {
    public class EmbeddedObjectModelRelationshipDefinition  : IModelRelationshipDefinition {
        private Type parentType;
        private Type modelRootType;

        public EmbeddedObjectModelRelationshipDefinition() : this(null) { }

        public EmbeddedObjectModelRelationshipDefinition(Type modelRootType) {
            this.modelRootType = modelRootType;
            this.parentType = typeof (ModelElement);
        }

        public ReadOnlyCollection<ModelElement> GetChildModelElements(ModelPath parentPath, CrossModelManager manager,
                                                                      string scope) {
            List<ModelElement> embeddedElements = new List<ModelElement>();
            foreach (DomainRoleInfo info in parentPath.TargetModelElement.GetDomainClass().LocalDomainRolesPlayed) {
                if(info.IsEmbedding) {
                    foreach (ModelElement embeddedElement in info.GetLinkedElements(parentPath.TargetModelElement)) {
                        embeddedElements.Add(embeddedElement);
                    }
                }
            }

            // return all the expected types under the model root
            return new ReadOnlyCollection<ModelElement>(embeddedElements);
        }

        public List<ModelPath> GetChildPaths(ModelPath parentPath, CrossModelManager manager, string scope) {
            ReadOnlyCollection<ModelElement> children = this.GetChildModelElements(parentPath, manager, scope);
            List<ModelPath> modelPaths = new List<ModelPath>();
            foreach (ModelElement child in children) {
                ModelPath newPath = parentPath.Clone() as ModelPath;
                newPath.Merge(new ModelPath(parentPath.TargetModelElement, child, scope));
                modelPaths.Add(newPath);
            }
            return modelPaths;
        }

        public Type ParentType {
            get { return parentType; }
            set { parentType = value; }
        }

        public Type ModelRootType {
            get { return modelRootType; }
            set { modelRootType = value; }
        }
    }
}